#pragma once
#include<iostream>
#include <string>
#include "log.hpp"
#include "Thread.hpp"
#include <vector>
#include <queue>
#include "mutex.hpp"
#include "Conddex.hpp"
namespace Threadpoolmodule
{
    const int gnums = 5;
    using namespace logmodule;
    using namespace ThreadModule;
    using namespace ConddexModule;
    using namespace MutexModule;
    template<typename T>
    class ThreadPool
    {
        private:
        //唤醒所有的线程
        void wakeupallthread()
        {
            lockguard guarder(_mutex);//加锁保护
            if(_sleepernum)//如果有正在休眠的线程，就去唤醒正在休眠的线程
            _cond.broadcast();//使用这个操作唤醒所有的线程 
            LOG(loglevel::INFO)<<"唤醒了所有的线程";
        }
        void wakeuponthread()
        {
            _cond.signal();
            LOG(loglevel::INFO)<<"唤醒了一个线程";
        }
        public:
        ThreadPool(int num = gnums)://创建若干个线程对象
        _nums(num)
        ,_isrunning(false)
        ,_sleepernum(0)
        {
            for(int i = 0;i<num;i++)
            {
                _threads.emplace_back([this]()
            {
                handertask();
            });
            LOG(loglevel::INFO)<<"start new thread success:"<<_threads[i].name();
            }
        }
        void start()
        {
            if(_isrunning)
            return ;
            _isrunning = true;
            for(auto &thread :_threads)
            {
                thread.start();
            }
        }

        void stop()
        {
            if(!_isrunning)
            return ;
            _isrunning = false;
            //唤醒所有的线程
            wakeupallthread();
        }

        void join()
        {
           
            for(auto &thread:_threads)
            {
                thread.join();
            }
        }

        void handertask()
        {
            char name[128];
            pthread_getname_np(pthread_self(),name,sizeof(name));
            while(true)
            {
                T t;
                {
                lockguard guarder(_mutex);
                //线程醒来所需要检查的条件（线程没退，任务队列是空的）
                while(_taskkq.empty()&&_isrunning==true)
                {
                    _sleepernum++;
                    _cond.wait(_mutex);//没有任务就会一直休眠
                    _sleepernum--;
                }
                //线程被唤醒，正常处理任务
                if(!_isrunning&&_taskkq.empty())
                {
                    LOG(loglevel::INFO)<<name<<"任务队列为空，运行状态为假，线程执行退出操作";
                    break;
                }
                t = _taskkq.front();//获取任务后，任务就是线程内部私有的
                _taskkq.pop();
                }
                //t();//处理任务
            }
        }
        bool Enqueue(const T &in)
        {
            //注意，只有当线程池运行时，才可以进行入队列，否则不能入队列
            //会造成任务越来越多的
            if(_isrunning)
            {
                lockguard guarder(_mutex);
            _taskkq.push(in);
            if(_threads.size()-_sleepernum==0)
            {
                //唤醒一个线程
                wakeuponethread();
            }
            return true;
            }
            return false;
        }
        ~ThreadPool()
        {}
        private:
        std::vector<Thread> _threads;//表示多个线程
        int _nums;//线程池中具体线程的个数
        std::queue<T> _taskkq;//任务队列
        Conddex _cond;
        Mutex _mutex;
        
        bool _isrunning;//方便对线程池进行停止
        int _sleepernum;//休眠线程的数目
    };
}